class Snake {
    //表示蛇的元素
    head: HTMLElement;
    //蛇的身体（包括蛇头）
    bodies: HTMLCollection;
    //获取蛇的容器
    element: HTMLElement
    constructor() {
        this.element = document.getElementById('snake') as HTMLElement;
        this.head = document.querySelector('#snake > div') as HTMLElement;
        this.bodies = (document.getElementById('snake') as HTMLElement).getElementsByTagName('div') as HTMLCollection;
    }

    //获取蛇X轴的坐标（蛇头的坐标）
    get X() {
        return this.head.offsetLeft
    }
    //获取蛇Y轴的坐标（蛇头的坐标）
    get Y() {
        return this.head.offsetTop
    }

    //设置蛇的X轴坐标
    set X(value: number) {
        //如果新值和旧值相同，则直接返回不再修改
        if (this.X === value) return
        //设置游戏区域的边界
        if (value < 0 || value > 290) throw new Error("蛇撞墙了!")
         //修改X时，是在修改水平坐标，蛇在左右移动，蛇在向左移动的时候，不嫩向右掉头，反之亦然
        if (this.bodies[1]&&(this.bodies[1] as HTMLElement ).offsetLeft===value){
            //如果新值value大于旧值X，则说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
            if (value>this.X) {
                value=this.X-10
            }else{
                value=this.X+10
            }
        }
        //移动身体
        this.moveBody()
        //移动蛇头
        this.head.style.left = value + 'px'

        this.checkHeadBody()
    }
    //设置蛇的Y轴坐标
    set Y(value: number) {
        if (this.Y === value) return
        if (value < 0 || value > 290) throw new Error("蛇撞墙了!");
        if (this.bodies[1]&&(this.bodies[1] as HTMLElement ).offsetTop===value){
            //如果新值value大于旧值X，则说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
            if (value>this.Y) {
                value=this.Y-10
            }else{
                value=this.Y+10
            }
        }
        this.moveBody()

        this.head.style.top = value + 'px'

        this.checkHeadBody()
       
    }

    //蛇增加身体的方法
    addBody() {
        //向element中的结束标签前面添加一个div
        this.element.insertAdjacentHTML("beforeend", "<div></div>")
    }

    //添加一个蛇身体移动的方法
    moveBody() {
        /*为了避免，修改以后前面的身体找不到后面的身体，所以得从后往前改
        *       后面的身体设置为前面身体的位置
        *            举例子
        *                第4节=第3节的位置
        *                第3节=第2节的位置
        *                第2节=蛇头的位置
        */
        //遍历获取所有的身体
        for (let i = this.bodies.length - 1; i > 0; i--) {
            //获取前面身体的位置

            let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
            let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;

            //将值设置到当前身体上
            ((this.bodies[i] as HTMLElement)).style.left = X + 'px';
            ((this.bodies[i] as HTMLElement)).style.top = Y + 'px'
        }
    }

    //蛇头与身体碰撞的逻辑
    checkHeadBody(){
        //获取所有的身体，价差其是否和舌头的坐标发生重叠
        for(let i=1;i<this.bodies.length;i++){
            //将改变后的位置，和蛇身体的位置做全等判断，true则表示撞到自己了
            let bd=this.bodies[i] as HTMLElement
            if (this.X===bd.offsetLeft&&this.Y===bd.offsetTop) {
                throw new Error('撞到自己了~')
            }
        
        }
    }

}

export default Snake